home *** CD-ROM | disk | FTP | other *** search
- /*
- RUN_ELF - Load and execute big endian ix86 ELF binaries
- Copyright (C) 2001-2002 Martin Blom <martin@blom.org>
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
- /*
- ** Based on code from the ppc.library emulator by Frank Wille:
- ** ppc.library emulation
- ** (c)1998-99 Frank Wille <frank@phoenix.owl.de>
- */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <exec/nodes.h>
- #include <dos/dos.h>
- #include <proto/dos.h>
- #include <proto/exec.h>
-
- #include <string.h>
-
- #include "elfloader.h"
-
- void
- KPrintFArgs( UBYTE* fmt,
- ULONG* args );
-
- #define KPrintF( fmt, ... ) \
- ({ \
- ULONG _args[] = { __VA_ARGS__ }; \
- KPrintFArgs( (fmt), _args ); \
- })
-
- void
- ReqA( const char* text, APTR args );
-
- #define Req( fmt, ... ) \
- ({ \
- ULONG _args[] = { __VA_ARGS__ }; \
- ReqA( (fmt), _args ); \
- })
-
-
- #define bswap_long(x) \
- ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
- (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
-
- #define bswap_short(x) \
- ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
-
-
- /*** From glibc2/elf.h *******************************************************/
-
- /* Intel 80386 specific definitions. */
-
- /* i386 relocs. */
-
- #define R_386_NONE 0 /* No reloc */
- #define R_386_32 1 /* Direct 32 bit */
- #define R_386_PC32 2 /* PC relative 32 bit */
- #define R_386_GOT32 3 /* 32 bit GOT entry */
- #define R_386_PLT32 4 /* 32 bit PLT address */
- #define R_386_COPY 5 /* Copy symbol at runtime */
- #define R_386_GLOB_DAT 6 /* Create GOT entry */
- #define R_386_JMP_SLOT 7 /* Create PLT entry */
- #define R_386_RELATIVE 8 /* Adjust by program base */
- #define R_386_GOTOFF 9 /* 32 bit offset to GOT */
- #define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */
- /* Keep this the last entry. */
- #define R_386_NUM 11
-
-
- /*** elfcommon.h *************************************************************/
-
- /* e_indent indexes */
- #define EI_NIDENT 16
- #define EI_MAG0 0
- #define EI_MAG1 1
- #define EI_MAG2 2
- #define EI_MAG3 3
- #define EI_CLASS 4
- #define EI_DATA 5
- #define EI_VERSION 6
- #define EI_PAD 7
-
- /* EI_CLASS */
- #define ELFCLASSNONE 0
- #define ELFCLASS32 1
- #define ELFCLASS64 2
-
- /* EI_DATA */
- #define ELFDATANONE 0
- #define ELFDATA2LSB 1
- #define ELFDATA2MSB 2
-
- /* e_type */
- #define ET_NONE 0 /* No file type */
- #define ET_REL 1 /* Relocatable file */
- #define ET_EXEC 2 /* Executable file */
- #define ET_DYN 3 /* Shared object file */
- #define ET_CORE 4 /* Core file */
- #define ET_LOPROC 0xFF00 /* Processor-specific */
- #define ET_HIPROC 0xFFFF /* Processor-specific */
-
- /* e_version */
- #define EV_NONE 0
- #define EV_CURRENT 1
-
- /* e_machine */
- #define EM_NONE 0
- #define EM_M32 1
- #define EM_SPARC 2
- #define EM_386 3
- #define EM_68K 4
- #define EM_88K 5
- #define EM_860 7
- #define EM_MIPS 8
- #define EM_MIPS_RS4_BE 10
- #define EM_SPARC64 11
- #define EM_PARISC 15
- #define EM_PPC_OLD 17
- #define EM_SPARC32PLUS 18
- #define EM_PPC 20
- #define EM_CYGNUS_POWERPC 0x9025
- #define EM_ALPHA 0x9026
-
- /* values for program header, p_type field */
- #define PT_NULL 0 /* Program header table entry unused */
- #define PT_LOAD 1 /* Loadable program segment */
- #define PT_DYNAMIC 2 /* Dynamic linking information */
- #define PT_INTERP 3 /* Program interpreter */
- #define PT_NOTE 4 /* Auxiliary information */
- #define PT_SHLIB 5 /* Reserved, unspecified semantics */
- #define PT_PHDR 6 /* Entry for header table itself */
- #define PT_LOPROC 0x70000000 /* Processor-specific */
- #define PT_HIPROC 0x7FFFFFFF /* Processor-specific */
-
- /* Program segment permissions, in program header p_flags field */
- #define PF_X (1 << 0) /* Segment is executable */
- #define PF_W (1 << 1) /* Segment is writable */
- #define PF_R (1 << 2) /* Segment is readable */
- #define PF_MASKPROC 0xF0000000 /* Processor-specific reserved bits */
-
- /* special sections indexes */
- #define SHN_UNDEF 0
- #define SHN_ABS 0xfff1
- #define SHN_COMMON 0xfff2
-
- /* sh_type */
- #define SHT_NULL 0 /* Section header table entry unused */
- #define SHT_PROGBITS 1 /* Program specific (private) data */
- #define SHT_SYMTAB 2 /* Link editing symbol table */
- #define SHT_STRTAB 3 /* A string table */
- #define SHT_RELA 4 /* Relocation entries with addends */
- #define SHT_HASH 5 /* A symbol hash table */
- #define SHT_DYNAMIC 6 /* Information for dynamic linking */
- #define SHT_NOTE 7 /* Information that marks file */
- #define SHT_NOBITS 8 /* Section occupies no space in file */
- #define SHT_REL 9 /* Relocation entries, no addends */
- #define SHT_SHLIB 10 /* Reserved, unspecified semantics */
- #define SHT_DYNSYM 11 /* Dynamic linking symbol table */
- #define SHT_LOPROC 0x70000000 /* Processor-specific semantics, lo */
- #define SHT_HIPROC 0x7FFFFFFF /* Processor-specific semantics, hi */
- #define SHT_LOUSER 0x80000000 /* Application-specific semantics */
- #define SHT_HIUSER 0x8FFFFFFF /* Application-specific semantics */
-
- /* sh_flags */
- #define SHF_WRITE (1 << 0) /* Writable data during execution */
- #define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
- #define SHF_EXECINSTR (1 << 2) /* Executable machine instructions */
- #define SHF_MASKPROC 0xF0000000 /* Processor-specific semantics */
-
- /* Values of note segment descriptor types for core files. */
- #define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
- #define NT_FPREGSET 2 /* Contains copy of fpregset struct */
- #define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
-
- #define STN_UNDEF 0 /* undefined symbol index */
-
- /* ST_BIND */
- #define STB_LOCAL 0 /* Symbol not visible outside obj */
- #define STB_GLOBAL 1 /* Symbol visible outside obj */
- #define STB_WEAK 2 /* Like globals, lower precedence */
- #define STB_LOPROC 13 /* Application-specific semantics */
- #define STB_HIPROC 15 /* Application-specific semantics */
-
- /* ST_TYPE */
- #define STT_NOTYPE 0 /* Symbol type is unspecified */
- #define STT_OBJECT 1 /* Symbol is a data object */
- #define STT_FUNC 2 /* Symbol is a code object */
- #define STT_SECTION 3 /* Symbol associated with a section */
- #define STT_FILE 4 /* Symbol gives a file name */
- #define STT_LOPROC 13 /* Application-specific semantics */
- #define STT_HIPROC 15 /* Application-specific semantics */
-
- /* Dynamic section tags */
- #define DT_NULL 0
- #define DT_NEEDED 1
- #define DT_PLTRELSZ 2
- #define DT_PLTGOT 3
- #define DT_HASH 4
- #define DT_STRTAB 5
- #define DT_SYMTAB 6
- #define DT_RELA 7
- #define DT_RELASZ 8
- #define DT_RELAENT 9
- #define DT_STRSZ 10
- #define DT_SYMENT 11
- #define DT_INIT 12
- #define DT_FINI 13
- #define DT_SONAME 14
- #define DT_RPATH 15
- #define DT_SYMBOLIC 16
- #define DT_REL 17
- #define DT_RELSZ 18
- #define DT_RELENT 19
- #define DT_PLTREL 20
- #define DT_DEBUG 21
- #define DT_TEXTREL 22
- #define DT_JMPREL 23
- #define DT_LOPROC 0x70000000
- #define DT_HIPROC 0x7fffffff
-
- /*** elf32.h *****************************************************************/
-
- typedef unsigned char uint8;
- typedef unsigned short uint16;
- typedef unsigned long uint32;
-
-
- struct Elf32_Ehdr {
- unsigned char e_ident[EI_NIDENT];
- uint16 e_type;
- uint16 e_machine;
- uint32 e_version;
- uint32 e_entry;
- uint32 e_phoff;
- uint32 e_shoff;
- uint32 e_flags;
- uint16 e_ehsize;
- uint16 e_phentsize;
- uint16 e_phnum;
- uint16 e_shentsize;
- uint16 e_shnum;
- uint16 e_shstrndx;
- };
-
- struct Elf32_Shdr {
- uint32 sh_name;
- uint32 sh_type;
- uint32 sh_flags;
- uint32 sh_addr;
- uint32 sh_offset;
- uint32 sh_size;
- uint32 sh_link;
- uint32 sh_info;
- uint32 sh_addralign;
- uint32 sh_entsize;
- };
-
- struct Elf32_Sym {
- uint32 st_name;
- uint32 st_value;
- uint32 st_size;
- uint8 st_info;
- uint8 st_other;
- uint16 st_shndx;
- };
-
- /* st_info */
- #define ELF32_ST_BIND(i) ((i)>>4)
- #define ELF32_ST_TYPE(i) ((i)&0xf)
- #define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
-
- struct Elf32_Rel {
- uint32 r_offset;
- uint32 r_info;
- };
-
- struct Elf32_Rela {
- uint32 r_offset;
- uint32 r_info;
- uint32 r_addend;
- };
-
- /* r_info */
- #define ELF32_R_SYM(i) ((i)>>8)
- #define ELF32_R_TYPE(i) ((unsigned char)(i))
- #define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t))
-
- /*** elfobject.h *************************************************************/
-
- struct ELFSection { /* prog. sections for new tasks */
- char *name;
- APTR address; /* physical RAM address or NULL */
- UWORD flags;
- UWORD alignment;
- long offset; /* file offset and section size */
- ULONG size;
- int nrel; /* number of relocs */
- struct Elf32_Rela *relocs; /* array of Elf32_Rela structs */
- };
-
- #define ElfSecB_NOBITS 0 /* bss section */
- #define ElfSecF_NOBITS 1
- #define ElfSecB_RELA 1 /* Relocs are of .rela type */
- #define ElfSecF_RELA 2
-
-
- struct ElfObject {
- UWORD flags;
- UWORD pad;
- const struct ELFDynSymbols* user_syms;/* User-provided symbols */
- BPTR handle; /* ELF file handle */
- char *secnames; /* .shstrtab - section names */
- char *symnames; /* .strtab - symbol mames */
- struct Elf32_Ehdr *header; /* the ELF file header */
- struct Elf32_Sym *symtab; /* .symtab - symbol table */
- uint32 nsyms; /* number of symbols */
- uint32 gsyms; /* first global symbol */
- struct ELFSection **sections; /* ELFSection pointers */
- uint32 nsects; /* number of sections */
- };
-
- #define ElfObjB_Relocated 0 /* Object is relocated */
- #define ElfObjF_Relocated 1
-
- /*** relocnames.c ************************************************************/
-
- const char *reloc_name[] = {
- "R_386_NONE",
- "R_386_32",
- "R_386_PC32",
- "R_386_GOT32",
- "R_386_PLT32",
- "R_386_COPY",
- "R_386_GLOB_DAT",
- "R_386_JMP_SLOT",
- "R_386_RELATIVE",
- "R_386_GOTOFF",
- "R_386_GOTPC"
- };
-
- /*** ppcobject.c *************************************************************/
-
-
- static void
- freeelfobj(struct ElfObject *elfobj);
-
- static BOOL
- loadelf32(struct ElfObject *eo,struct Elf32_Shdr *shdrs);
-
- static BOOL
- loadprogram(struct ElfObject *eo, APTR* entry, BPTR* seg );
-
- static void
- freeprogram(struct ElfObject *eo);
-
- static BPTR
- makeseglist( struct ElfObject *eo, APTR text_section );
-
- static BOOL
- relocate(struct ElfObject *eo);
-
- static void*
- allocvec( ULONG byteSize, ULONG attributes );
-
- static void
- freevec( void* memoryBlock );
-
- static void*
- alloc_dosseg( size_t size );
-
- void
- free_dosseg( void* addr );
-
- static BPTR
- opstream(struct ElfObject *eo, const char* name );
-
- static BOOL
- clstream(struct ElfObject *eo);
-
- static BOOL
- rdstream(struct ElfObject *eo,void *buf,long len);
-
- static long
- skstream(struct ElfObject *eo,long offs,long mode);
-
- static BOOL
- prstream(struct ElfObject *eo,long offs,void *buf,long len);
-
- static void*
- readsection(struct ElfObject *eo,struct Elf32_Shdr *sh);
-
- static struct ELFSection*
- progsection(struct ElfObject *eo, struct Elf32_Shdr *sh);
-
- static BOOL
- common_symbols(struct ElfObject *eo);
-
- static BOOL
- getrelocs(struct ElfObject *eo,struct Elf32_Shdr *sh);
-
- static const char ELFid[4] = {
- 0x7f,'E','L','F'
- };
-
- void*
- ELFLoadObject( const char* objname, BPTR* seg, const struct ELFDynSymbols* syms )
- {
- struct ElfObject *elfobj = NULL;
-
- /* allocate ElfObject structure */
-
- elfobj = allocvec( sizeof( struct ElfObject ), MEMF_ANY );
-
- if( elfobj != NULL )
- {
- memset(elfobj,0,sizeof(struct ElfObject));
-
- elfobj->user_syms = syms;
-
- elfobj->header = allocvec( sizeof( struct Elf32_Ehdr ), MEMF_ANY );
-
- if( elfobj->header != NULL )
- {
- /* open ELF stream for reading */
-
- elfobj->handle = opstream( elfobj, objname );
-
- if( elfobj->handle != NULL )
- {
- /* read and identify ELF 32bit PowerPC BigEndian header */
-
- if( rdstream( elfobj, elfobj->header, sizeof(struct Elf32_Ehdr) ) )
- {
- struct Elf32_Ehdr *hdr = elfobj->header;
-
- if (!strncmp(hdr->e_ident,ELFid,4) &&
- hdr->e_ident[EI_CLASS]==ELFCLASS32 &&
- hdr->e_ident[EI_DATA]==ELFDATA2MSB &&
- hdr->e_ident[EI_VERSION]==1 && hdr->e_version==1 &&
- (hdr->e_machine==EM_386) && hdr->e_type==ET_REL)
- {
- struct Elf32_Shdr *shdrs;
- ULONG shdrsize = (ULONG) hdr->e_shnum * (ULONG) hdr->e_shentsize;
-
- //Printf("elf32-386-be format recognized\n");
-
- shdrs = allocvec( shdrsize, MEMF_ANY);
-
- if( shdrs != NULL )
- {
- /* read section header table and parse rest of object */
-
- if( prstream( elfobj, hdr->e_shoff, shdrs, shdrsize ) )
- {
- if( loadelf32( elfobj, shdrs ) )
- {
- APTR text_entry;
- //Printf("ELF object loaded (0x%08lx)\n", elfobj );
- if( loadprogram( elfobj, &text_entry, seg ) ) {
- //Printf("Start of PPC code: 0x%08lx\n", text_entry );
- freevec( shdrs );
- return (elfobj);
- }
- }
- }
- freevec( shdrs );
- }
- }
- else
- {
- //KPrintF( "Not an ELF32-386-BE relocatable object.\n");
- }
- }
- }
- freeelfobj(elfobj);
- }
- }
-
- return (NULL);
- }
-
-
- void
- ELFUnLoadObject( void* obj )
- {
- struct ElfObject* elfobj = (struct ElfObject*) obj;
-
- if( obj == NULL )
- {
- return;
- }
-
- if(elfobj->sections != NULL && elfobj->nsects > 0 )
- {
- freeprogram(elfobj);
- }
-
- freeelfobj(elfobj);
- }
-
- static void freeelfobj(struct ElfObject *elfobj)
- /* free all memory connected to an ElfObject */
- {
- if (elfobj) {
- if (elfobj->handle)
- clstream(elfobj);
-
- if( elfobj->sections != NULL && elfobj->header != NULL )
- {
- int i;
-
- for( i = 0; i < elfobj->header->e_shnum+1; ++i )
- {
- freevec( elfobj->sections[i] );
- }
- }
-
- freevec(elfobj->secnames);
- freevec(elfobj->symnames);
- freevec(elfobj->header);
- freevec(elfobj->symtab);
- freevec(elfobj->sections);
- freevec(elfobj);
- }
- }
-
-
- static BOOL loadelf32(struct ElfObject *eo,struct Elf32_Shdr *shdrs)
- /* parse ELF object, initialize ElfObject structure */
- {
- struct Elf32_Ehdr *hdr = eo->header;
- uint16 i;
-
- if ((eo->secnames = readsection(eo,&shdrs[hdr->e_shstrndx])) &&
- (eo->sections = allocvec((hdr->e_shnum+1)*sizeof(void *),MEMF_ANY))) {
- memset(eo->sections,0,(hdr->e_shnum+1)*sizeof(void *));
- eo->nsects = hdr->e_shnum + 1; /* +1 section for COMMON symbols */
- for (i=1; i<hdr->e_shnum; i++) {
- switch (shdrs[i].sh_type) {
- case SHT_PROGBITS:
- case SHT_NOBITS:
- if (!(eo->sections[i] = progsection(eo,&shdrs[i])))
- return (FALSE);
- break;
- case SHT_SYMTAB:
- if (!(eo->symnames = readsection(eo,&shdrs[shdrs[i].sh_link]))
- || !(eo->symtab = readsection(eo,&shdrs[i])))
- return (FALSE);
- eo->nsyms = shdrs[i].sh_size / sizeof(struct Elf32_Sym);
- eo->gsyms = shdrs[i].sh_info;
- break;
- default:
- break;
- }
- }
- for (i=1; i<hdr->e_shnum; i++) {
- switch (shdrs[i].sh_type) {
- case SHT_REL:
- case SHT_RELA:
- if (!getrelocs(eo,&shdrs[i]))
- return (FALSE);
- break;
- default:
- break;
- }
- }
- /* allocate space for Common symbols */
- return (common_symbols(eo));
- }
- return (FALSE);
- }
-
- static BOOL loadprogram(struct ElfObject *eo, APTR* text_section, BPTR* seg )
- /* load all sections into memory and relocate them */
- {
- static const char *FN = "loadprogram(): ";
- struct ELFSection *s;
- uint8 *p;
- unsigned int i;
-
- for (i=0; i<(eo->nsects-1); i++) {
- if( (s = eo->sections[i]) != NULL ) {
-
- BOOL text = !strcmp(s->name,".text"); /* .text section flag */
- ULONG size = s->size;
-
- //Printf("%sSection '%s' (%ld bytes).\n", FN,s->name, s->size );
- if( size != 0 ) {
- // lcs: In order to be able to make a DOS memory segment out of
- // this later, we allocate 4 extra bytes BEFORE before the actual
- // section. This is handled by alloc_dosseg().
-
- if( (p = alloc_dosseg(size)) != NULL ) {
- s->address = (APTR)p; /* store section's base address */
- if (!(s->flags & ElfSecF_NOBITS)) {
- /* a PROGBITS section - load it from file */
-
- //Printf("%sreading section %s\n",FN,s->name);
- if (prstream(eo,s->offset,p,s->size)) {
- if (text) {
- /* get start address of PPC program in .text */
- *text_section = p;
- }
- }
- else {
- *text_section = NULL;
- break;
- }
- }
- }
- else {
- Req("Failed to allocate %ld bytes "
- "for section '%s'.\n",size,(ULONG)s->name);
- *text_section = NULL;
- break;
- }
- }
- }
- }
-
- if (*text_section != NULL) {
- if (!relocate(eo)) { /* relocate sections */
- *text_section = NULL;
- freeprogram(eo);
- }
- }
- else
- freeprogram(eo);
-
- /* Build a DOS segment list */
- *seg = makeseglist( eo, *text_section );
-
- if( *seg == 0 )
- {
- *text_section = NULL;
- freeprogram(eo);
- }
-
- //Printf("%sreturning with entry=0x%08lx\n",FN,entry);
- return (*text_section != NULL);
- }
-
-
- static void freeprogram(struct ElfObject *eo)
- {
- struct ELFSection *s;
- unsigned int i;
-
- for (i=0; i<eo->nsects; i++) {
- if( (s = eo->sections[i]) != NULL ) {
- if (s->address) {
- free_dosseg(s->address);
- s->address = NULL;
- }
- freevec( s->relocs );
- s->relocs = NULL;
- }
- }
- }
-
-
- static BPTR makeseglist( struct ElfObject *eo, APTR text_section )
- {
- struct ELFSection *s;
- unsigned int i;
- BPTR text_segment = 0;
- BPTR first_segment = NULL;
- BPTR* last_segment_ptr = NULL;
-
- for (i=0; i<eo->nsects; i++) {
- if( (s = eo->sections[i]) != NULL ) {
- if (s->address) {
- BPTR this_segment = MKBADDR( s->address ) - 1;
-
- if( s->address != text_section )
- {
- if( first_segment == 0 )
- {
- first_segment = this_segment;
- }
-
- if( last_segment_ptr != NULL )
- {
- *last_segment_ptr = this_segment;
- }
-
- last_segment_ptr = (BPTR*) ((ULONG) s->address - 4);
- }
- else
- {
- text_segment = this_segment;
- }
- }
- }
- }
-
- if( last_segment_ptr )
- {
- // Make sure the segment list is terminated
- *last_segment_ptr = 0;
- }
-
- if( first_segment && text_segment )
- {
- *(BPTR*)(BADDR(text_segment)) = first_segment;
- }
-
- if( text_segment )
- {
- for (i=0; i<eo->nsects; i++) {
- if( (s = eo->sections[i]) != NULL ) {
- // Segment is not owned by us anymore!
- s->address = NULL;
- }
- }
- }
-
- #if 0
- {
- int i = 1;
- BPTR segment;
-
- Printf( "Verifying seglist\n" );
-
- segment = text_segment;
-
- while( segment != 0 )
- {
- Printf( "Segment %ld at 0x%08lx/%08lx, length %ld\n",
- i,
- segment, (ULONG) BADDR( segment ),
- *(ULONG*)( BADDR( segment - 1 ) ) );
-
- segment = *(ULONG*)( BADDR( segment ) );
- ++i;
- }
- }
-
- return 0;
- #endif
-
- return text_segment;
- }
-
-
- #if 0
- static void write_short( void* addr, short value, BOOL little_endian )
- {
- if(little_endian)
- {
- value = bswap_short(value);
- }
-
- *((short*) addr) = value;
- }
- #endif
-
- static void write_long( void* addr, long value, BOOL little_endian )
- {
- if(little_endian)
- {
- value = bswap_long(value);
- }
-
- *((long*) addr) = value;
- }
-
- #if 0
- static short read_short( void* addr, BOOL little_endian )
- {
- short value;
-
- value = *((short*) addr);
-
- if(little_endian)
- {
- value = bswap_short(value);
- }
-
- return value;
- }
- #endif
-
- static long read_long( void* addr, BOOL little_endian )
- {
- long value;
-
- value = *((long*) addr);
-
- if(little_endian)
- {
- value = bswap_long(value);
- }
-
- return value;
- }
-
-
- static BOOL relocate(struct ElfObject *eo)
- {
- struct ELFSection *es;
- unsigned int shndx;
-
- for (shndx=0; shndx<(eo->nsects-1); shndx++) {
- if( (es = eo->sections[shndx]) != NULL ) {
- BOOL rela = (es->flags & ElfSecF_RELA) != 0;
- BOOL little = strcmp(es->name,".text") == 0;
- struct Elf32_Rela *r;
- int i;
-
- //Printf("relocate(): relocating section %s "
- // "at 0x%08lx\n",es->name,es->address);
-
- for (i=0,r=es->relocs; i<es->nrel; i++,r++) {
- struct Elf32_Sym *sym = &eo->symtab[ELF32_R_SYM(r->r_info)];
- long s;
- uint8 *p = (uint8 *)es->address + r->r_offset;
-
- switch (sym->st_shndx) {
- case SHN_UNDEF:
- {
- const struct ELFDynSymbols* syms = eo->user_syms;
-
- while( syms->name != NULL )
- {
- if( strcmp( eo->symnames+sym->st_name, syms->name)==0 )
- {
- s = (ULONG) syms->addr;
- break;
- }
-
- ++syms;
- }
-
- if( syms->name == NULL )
- {
- Req( "Undefined symbol: '%s'", (ULONG)eo->symnames+sym->st_name);
- return FALSE;
- }
- break;
- }
-
- case SHN_ABS:
- s = sym->st_value;
- break;
-
- case SHN_COMMON:
- Req( "Common symbol: '%s'", (ULONG) eo->symnames+sym->st_name);
- return FALSE;
-
- default:
- s = (long)eo->sections[sym->st_shndx]->address + sym->st_value;
- break;
- }
- #if 0
- Printf("*** Now doing relocation type %s "
- "at %s+%ld referencing "
- "symbol %s+%ld in section %s at %08lx\n",
- reloc_name[ELF32_R_TYPE(r->r_info)],es->name,r->r_offset,
- eo->symnames+sym->st_name,sym->st_value,
- eo->sections[sym->st_shndx]->name, eo->sections[sym->st_shndx]->address);
- #endif
-
- switch (ELF32_R_TYPE(r->r_info)) {
- case R_386_NONE:
- break;
-
- case R_386_32:
- //Printf( "Value: %08lx (raw: %08lx)\n", read_long(p, little), *(long*)p);
- if (rela)
- write_long( p, s + r->r_addend, little );
- else
- write_long( p, read_long( p, little ) + s, little );
- //Printf( "Value: %08lx (raw: %08lx)\n", read_long(p, little), *(long*)p);
- break;
-
- case R_386_PC32:
- //Printf( "Value: %08lx (raw: %08lx)\n", read_long(p, little), *(long*)p);
- if (rela)
- write_long( p, s + r->r_addend - (long) p, little );
- else
- write_long( p, read_long( p, little ) + s - (long) p, little );
- //Printf( "Value: %08lx (raw: %08lx)\n", read_long(p, little), *(long*)p);
- break;
-
- default:
- Req("Relocation type %s\nat %s+%ld referencing\n"
- "symbol %s+%ld\nis not supported.",
- (ULONG)reloc_name[ELF32_R_TYPE(r->r_info)],(ULONG)es->name,r->r_offset,
- (ULONG)eo->symnames+sym->st_name,sym->st_value);
- return (FALSE);
- }
- }
- }
- }
- return (TRUE);
- }
-
- static void*
- allocvec( ULONG byteSize, ULONG attributes )
- {
- void* result = AllocVec( byteSize, attributes );
- // Printf( "%08lx: Allocated %ld bytes\n", result, byteSize );
- return result;
- }
-
- static void
- freevec( void* memoryBlock )
- {
- // if( memoryBlock != NULL )
- // {
- // Printf( "%08lx: Freeing\n", memoryBlock );
- // }
-
- return FreeVec( memoryBlock );
- }
-
- static void*
- alloc_dosseg( size_t size )
- {
- void* address;
-
- /* align size to 32 bytes, add 8 bytes and allocate 32-byte aligned
- memory */
-
- size = ((size+31)&~31);
-
- address = AllocMem( size + 8 + 31, MEMF_ANY );
-
- if( address != NULL )
- {
- Forbid();
- FreeMem( address, size + 8 + 31 );
- address = AllocAbs( size + 8,
- (void*) (((ULONG) (address + 8 + 31) & ~31) - 8) );
- Permit();
- }
-
- if( address != NULL )
- {
- // Printf( "%08lx: Allocated %ld bytes (segment)\n", address, size + 8 );
- *(ULONG*) address = size + 8;
- memset( address + 4, 0, size + 4 );
- // Printf( "alloc_dosseg( %ld ) -> %08lx\n", size, address + 8 );
- return address + 8;
- }
- else
- {
- return NULL;
- }
- }
-
-
- void
- free_dosseg( void* addr )
- {
- // Printf( "free_dosseg( %08lx ) -> FreeMem( %08lx, %ld )\n", addr, addr - 8, *(ULONG*)(addr - 8) );
-
- // if( addr != NULL )
- // {
- // Printf( "%08lx: Freeing (seg)\n", addr );
- // }
-
- FreeMem( addr - 8, *(ULONG*)(addr - 8) );
- }
-
-
- static BPTR
- opstream(struct ElfObject *eo __attribute__ ((unused)), const char* name )
- {
- BPTR handle = NULL;
-
- if( name != NULL )
- {
- handle = Open( (char*) name, MODE_OLDFILE );
- }
-
- return (handle);
- }
-
-
- static BOOL
- clstream(struct ElfObject *eo)
- {
- Close( eo->handle );
- return TRUE;
- }
-
-
- static BOOL
- rdstream(struct ElfObject *eo,void *buf,long len)
- {
- long r;
-
- r = Read( eo->handle, buf, len );
-
- if( r != len )
- {
- return (FALSE);
- }
- return (TRUE);
- }
-
-
- static long
- skstream(struct ElfObject *eo,long offs,long mode)
- {
- long r;
-
- r = Seek( eo->handle, offs, mode );
- return (r);
- }
-
-
- static BOOL
- prstream(struct ElfObject *eo,long offs,void *buf,long len)
- /* position and read stream */
- {
- if (skstream(eo,offs,OFFSET_BEGINNING) != -1)
- return (rdstream(eo,buf,len));
- return FALSE;
- }
-
-
- static void *readsection(struct ElfObject *eo,struct Elf32_Shdr *sh)
- /* allocate memory and read section contents */
- {
- void *p;
-
- if( (p = allocvec(sh->sh_size,MEMF_ANY)) != NULL )
- {
- if (prstream(eo,sh->sh_offset,p,sh->sh_size))
- {
- return (p);
- }
- else
- {
- freevec( p );
- }
- }
- return (NULL);
- }
-
-
- static struct ELFSection *progsection(struct ElfObject *eo,
- struct Elf32_Shdr *sh)
- /* Create Section structure from Elf32_Shdr. The contents of these */
- /* sections will be loaded and relocated on demand, e.g. if a new task */
- /* is created. */
- {
- struct ELFSection *s;
-
- if( (s = allocvec(sizeof(struct ELFSection),MEMF_ANY)) != NULL ) {
- memset(s,0,sizeof(struct ELFSection));
- s->name = eo->secnames + sh->sh_name;
- s->flags = sh->sh_type==SHT_NOBITS ? ElfSecF_NOBITS:0;
- s->alignment = (uint8)sh->sh_addralign;
- s->offset = sh->sh_offset;
- s->size = sh->sh_size;
- return (s);
- }
- return (NULL);
- }
-
-
- static BOOL common_symbols(struct ElfObject *eo)
- /* Create a and initialize Section structure for Common symbols. */
- {
- // static const char *FN = "common_symbols(): ";
- static const char *bssname = ".bss";
- struct ELFSection *s = NULL;
- struct Elf32_Sym *sym;
- // uint16 *relocp;
- uint32 offset = 0,idx = 0,cnt=0;
- unsigned int i;
-
- /* First try to find a .bss, where Common symbols could be appended */
- for (i=0; i<(eo->nsects-1); i++) {
- if( (s = eo->sections[i]) != NULL ) {
- if (!strcmp(s->name,bssname) && (s->flags & ElfSecF_NOBITS)) {
- idx = i;
- offset = s->size;
- //Printf("%sfound %s at index %ld with size=%ld\n",
- // FN,bssname,idx,offset);
- break;
- }
- else
- s = NULL;
- }
- }
-
- if (!s) {
- /* No .bss section present, allocate an own one */
- if( (s = allocvec(sizeof(struct ELFSection),MEMF_ANY)) != NULL ) {
- memset(s,0,sizeof(struct ELFSection));
- s->name = (char*)bssname;
- s->flags = ElfSecF_NOBITS;
- s->alignment = 32;
- offset = 0;
- idx = eo->nsects-1;
- eo->sections[idx] = s;
- //Printf("%screated new %s at index %ld\n",FN,bssname,idx);
- }
- else
- return (FALSE);
- }
-
- /* Ok, search for COMMON symbols now */
- for (i=1,sym=&eo->symtab[1]; i<eo->nsyms; i++,sym++) {
- if (sym->st_shndx == SHN_COMMON) {
- offset = (offset + sym->st_value-1) & ~(sym->st_value-1);
- sym->st_value = offset;
- sym->st_shndx = idx;
- offset += sym->st_size;
- cnt++;
- }
- }
- // Printf("%sassigned %ld common symbols (%ld bytes)\n",
- // FN,cnt,offset-s->size);
- s->size = offset; /* set new .bss section size */
-
- return (TRUE);
- }
-
-
- static BOOL getrelocs(struct ElfObject *eo,struct Elf32_Shdr *sh)
- /* read relocation entries for a section */
- {
- uint32 rsize = sh->sh_entsize;
- int nrelocs = (int)(sh->sh_size/rsize);
- struct ELFSection *s = eo->sections[sh->sh_info];
-
-
- s->nrel = nrelocs;
- if (sh->sh_type == SHT_RELA) {
- s->flags |= ElfSecF_RELA;
- if( (s->relocs = readsection(eo,sh)) != NULL )
- return (TRUE);
- }
- else {
- struct Elf32_Rela *r;
-
- if ((r = s->relocs = allocvec(nrelocs*sizeof(struct Elf32_Rela),
- MEMF_ANY)) &&
- (skstream(eo,sh->sh_offset,OFFSET_BEGINNING) != -1)) {
- while (nrelocs--) {
- r->r_addend = 0;
- if (!rdstream(eo,r,sizeof(struct Elf32_Rel)))
- return (FALSE);
- r++;
- }
- return (TRUE);
- }
- }
- return (FALSE);
- }
-